import Particle from "@/views/404/Particle";

interface IMouse {
  radius: number;
  x: number;
  y: number;
}
export default class Effect {
  context: any;
  canvasWidth: number;
  canvasHeight: number;
  textX: number;
  textY: number;
  fontSize: number;
  lineHeight: number;
  maxTextWidth: number;
  verticalOffset: number;
  particles: any[];
  gap: number;
  mouse: IMouse;
  constructor(context: any, canvasWidth: number, canvasHeight: number) {
    this.context = context;
    this.canvasWidth = canvasWidth;
    this.canvasHeight = canvasHeight;
    this.textX = this.canvasWidth / 2;
    this.textY = this.canvasHeight / 2;
    this.fontSize = 300;
    this.lineHeight = this.fontSize * 0.9;
    this.maxTextWidth = this.canvasWidth * 0.7;
    this.verticalOffset = 0;
    // particle text
    this.particles = [];
    this.gap = 15;
    this.mouse = {
      radius: 20000,
      x: 0,
      y: 0,
    };
    window.addEventListener("mousemove", (e) => {
      this.mouse.x = e.x;
      this.mouse.y = e.y;
    });
  }
  wrapText(text: string) {
    // canvas settings
    this.context.fillStyle = "white";
    this.context.textAlign = "center";
    this.context.textBaseline = "middle";
    this.context.lineWidth = 1;
    this.context.strokeStyle = "white";
    this.context.font = this.fontSize + "px fantasy";
    // break multiline text
    const linesArray = [];
    const words = text.split(" ");
    let lineCounter = 0;
    let line = "";
    for (let i = 0; i < words.length; i++) {
      const testLine = line + words[i] + " ";
      if (this.context.measureText(testLine).width > this.maxTextWidth) {
        line = words[i] + " ";
        lineCounter++;
      } else {
        line = testLine;
      }
      linesArray[lineCounter] = line;
    }
    const textHeight = this.lineHeight * lineCounter;
    this.textY = this.canvasHeight / 2 - textHeight / 2 + this.verticalOffset;
    linesArray.forEach((el, index) => {
      this.context.fillText(el, this.textX, this.textY + index * this.lineHeight);
      //this.context.strokeText(el, this.textX, this.textY + (index * this.lineHeight));
    });
    this.convertToParticles();
  }
  convertToParticles() {
    this.particles = [];
    const pixels = this.context.getImageData(0, 0, this.canvasWidth, this.canvasHeight).data;
    this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    for (let y = 0; y < this.canvasHeight; y += this.gap) {
      for (let x = 0; x < this.canvasWidth; x += this.gap) {
        const index = (y * this.canvasWidth + x) * 4;
        const alpha = pixels[index + 3];
        if (alpha > 0) {
          const red = pixels[index];
          const green = pixels[index + 1];
          const blue = pixels[index + 2];
          const color = "rgb(" + red + "," + green + "," + blue + ")";
          this.particles.push(new Particle(this, x, y, color));
        }
      }
    }
  }
  constellations() {
    for (let a = 0; a < this.particles.length; a++) {
      for (let b = a; b < this.particles.length; b++) {
        const dx = this.particles[a].x - this.particles[b].x;
        const dy = this.particles[a].y - this.particles[b].y;
        const distance = Math.hypot(dy, dx);
        const connectDistance = this.gap * 2;
        if (distance < connectDistance && this.particles[a].x > this.mouse.x) {
          const position = this.particles[a].size / 2;
          this.context.beginPath();
          this.context.moveTo(this.particles[a].x + position, this.particles[a].y + position);
          this.context.lineTo(this.particles[b].x + position, this.particles[b].y + position);
          this.context.strokeStyle = this.particles[a].color;
          this.context.stroke();
        }
      }
    }
  }
  render() {
    this.particles.forEach((particle) => {
      particle.draw();
      particle.update();
    });
    this.constellations();
  }
  resize(width: number, height: number) {
    this.canvasWidth = width;
    this.canvasHeight = height;
    this.textX = this.canvasWidth / 2;
    this.textY = this.canvasHeight / 2;
    this.maxTextWidth = this.canvasWidth * 0.8;
  }
}
